package com.ruoyi.pos.api.service.user.impl;

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.AuditStatusEnum;
import com.ruoyi.common.enums.TeamTypeEnum;
import com.ruoyi.common.enums.YesOrNoEnums;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.common.utils.weCat.WeCatUtils;
import com.ruoyi.pos.api.dto.user.DataStatisticsDto;
import com.ruoyi.pos.api.dto.user.UserDto;
import com.ruoyi.pos.api.service.user.ILoginService;
import com.ruoyi.pos.api.utils.CommonUtils;
import com.ruoyi.pos.api.vo.user.DataStatisticsVo;
import com.ruoyi.pos.api.vo.user.UserInfoVo;
import com.ruoyi.pos.web.domain.TGradeInfo;
import com.ruoyi.pos.web.domain.TUserInfo;
import com.ruoyi.pos.web.domain.TUserTeamInfo;
import com.ruoyi.pos.web.mapper.TGradeInfoMapper;
import com.ruoyi.pos.web.mapper.TStatisticInfoMapper;
import com.ruoyi.pos.web.mapper.TUserInfoMapper;
import com.ruoyi.pos.web.mapper.TUserTeamInfoMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * @Author luobo
 * @Date 2021/9/17 11:28
 */
@Service
public class LoginServiceImpl implements ILoginService {
    private static final Logger log = LoggerFactory.getLogger(LoginServiceImpl.class);

    @Autowired
    private RedisCache redisCache;
    @Autowired
    private CommonUtils commonUtils;
    @Autowired
    private WeCatUtils weCatUtils;
    //@Value("${user.userTeam}")
    //private String userTeam;

    @Autowired
    private TUserInfoMapper userInfoMapper;
    @Autowired
    private TUserTeamInfoMapper userTeamInfoMapper;
    @Autowired
    private TGradeInfoMapper userGradeInfoMapper;
    @Autowired
    private TStatisticInfoMapper tStatisticInfoMapper;
    @Autowired
    private TGradeInfoMapper tGradeInfoMapper;

    //用户注册
    @Override
    @Transactional
    public UserInfoVo userRegister(UserDto userDto) throws Exception {
        String redisCode = redisCache.getVerifyCode(userDto.getUserPhone());
        if (StringUtils.isEmpty(redisCode)) {
            throw new RuntimeException("验证码过期");
        }
        /*if (!redisCode.equals(userDto.getVerifyCode())) {
            throw new RuntimeException("验证码错误，请重新输入");
        }*/
        if (StringUtils.isEmpty(userDto.getPassword())) {
            throw new RuntimeException("密码不能为空");
        }
        //校验用户是否已存在
        TUserInfo user = userInfoMapper.selectUserByUserPhone(userDto.getUserPhone());
        if (null != user) {
            throw new RuntimeException("该手机号已被注册");
        }
        Date date = DateUtils.getNowDate();
        user = commonUtils.generateTUserInfo(date);
        if (StringUtils.isEmpty(userDto.getOpenId())) {
            throw new RuntimeException("微信openId不能为空");
        }
        user.setOpenId(userDto.getOpenId());

        String salt = SaltUtils.createSalt();
        String password = SaltUtils.salt(userDto.getPassword(), salt);
        user.setSalt(salt);
        user.setUserPhone(userDto.getUserPhone());
        user.setUserName(userDto.getUserName());
        user.setPassword(password);
        Integer integer = userInfoMapper.queryUserCount();

        //插入一条自身的直营关系表
        TUserTeamInfo team = commonUtils.generateUserTeamInfo(
                user.getUserId(),
                user.getUserId(),
                TeamTypeEnum.DIRECTLY.getCode(),
                date);
        userTeamInfoMapper.insertTUserTeamInfo(team);

        //插入一条自身的团队关系表
        team = commonUtils.generateUserTeamInfo(
                user.getUserId(),
                user.getUserId(),
                TeamTypeEnum.TEAM.getCode(),
                date);
        userTeamInfoMapper.insertTUserTeamInfo(team);
        List<TGradeInfo> gradeList = userGradeInfoMapper.selectTGradeInfoList(new TGradeInfo());
        TGradeInfo grade = new TGradeInfo();
        user.setInviteImg(createOrderQrCode(user.getInviteCode(), userDto.getUserUrl()));
        if (integer > 0) {
            if (StringUtils.isEmpty(userDto.getInviteCode())) {
                throw new RuntimeException("请填写邀请码");
            }
            //设置会员级别
            grade = gradeList.stream().min(Comparator.comparing(TGradeInfo::getSort)).get(); //默认取最小会员级别
            String inviteCodeMin = userInfoMapper.selectInviteCodeForMin();
            if (inviteCodeMin.equals(userDto.getInviteCode())) { //说明是通过平台的邀请码注册，则默认为核心V9
                grade = gradeList.stream().max(Comparator.comparing(TGradeInfo::getSort)).get();
            }
            //redisCache.setCacheObject(userTeam + ":" + user.getUserId(), user.getUserId());
            //根据邀请码查询用户信息
            TUserInfo supUser = userInfoMapper.selectUserByInviteCode(userDto.getInviteCode());
            if (null == supUser) {
                throw new RuntimeException("无效邀请码");
            }
            user.setSuperiorUserId(supUser.getUserId());
            user.setSuperiorUserName(supUser.getUserName());
            //插入直营上级的直营关系表
            team = commonUtils.generateUserTeamInfo(
                    supUser.getUserId(),
                    user.getUserId(),
                    TeamTypeEnum.DIRECTLY.getCode(),
                    date);
            userTeamInfoMapper.insertTUserTeamInfo(team);

            //找到直营上级的团队列表，在每个人的团队下面，都增加一条记录
            TUserTeamInfo mapper = new TUserTeamInfo();
            mapper.setSubUserId(supUser.getUserId());
            mapper.setTeamType(TeamTypeEnum.TEAM.getCode());
            List<TUserTeamInfo> teamList = userTeamInfoMapper.selectTUserTeamInfoList(mapper);
            String userId = user.getUserId();
            Optional.ofNullable(teamList).ifPresent(list -> {
                list.stream().forEach(bean -> {
                    TUserTeamInfo supteam = new TUserTeamInfo();
                    BeanUtils.copyProperties(bean, supteam);
                    supteam.setId(IdUtils.simpleUUID());
                    supteam.setSubUserId(userId);
                    supteam.setCreateTime(date);
                    userTeamInfoMapper.insertTUserTeamInfo(supteam);
                });
            });
        }else {
            grade = gradeList.stream().min(Comparator.comparing(TGradeInfo::getSort)).get();
        }
        user.setGradeId(grade.getId());
        user.setAutonymType(YesOrNoEnums.NO.getCode());//是否实名认证（0：否，1：是）
        userInfoMapper.insertTUserInfo(user);
        UserInfoVo vo = new UserInfoVo();
        BeanUtils.copyProperties(user, vo);
        transUserInfoVo(vo);
        redisCache.setUserToken(user.getToken(), user.getUserId());
        return vo;
    }

    //openId登录
    @Override
    public UserInfoVo loginByOpenId(UserDto userDto) throws Exception {
        if (StringUtils.isEmpty(userDto.getCode())) {
            throw new RuntimeException("code不能为空");
        }
        /*if (1 == 1) {
            log.info("code:" + userDto.getCode());
            throw new RuntimeException("接口获取的code参数：" + userDto.getCode());
        }*/
        JSONObject openJson = weCatUtils.queryWxOpenIdForH5(userDto.getCode());
        if (null == openJson || StringUtils.isNotEmpty(openJson.getString("errcode"))) {
            throw new RuntimeException("获取微信openId失败！");
        }
        String openId = openJson.getString("openid");
        if (StringUtils.isEmpty(openId)) {
            throw new RuntimeException("获取微信openId为空！");
        }
        TUserInfo user = userInfoMapper.selectUserByOpenId(openId);
        UserInfoVo vo = new UserInfoVo();
        if (null == user) {
            user = new TUserInfo();
            user.setOpenId(openId);
            BeanUtils.copyProperties(user, vo);
        } else {
            if (YesOrNoEnums.NO.getCode().equals(user.getUserStatus())) {
                throw new RuntimeException("您已被禁用，无法完成登录");
            }
            redisCache.setUserToken(user.getToken(), user.getUserId());
            DataStatisticsDto dto = new DataStatisticsDto();
            dto.setUserId(user.getUserId());
            DataStatisticsVo statisticsVo = tStatisticInfoMapper.queryTStatisticSum(dto);
            TGradeInfo grade = tGradeInfoMapper.selectTGradeInfoById(user.getGradeId());
            BeanUtils.copyProperties(user, vo);
            vo.setGradeCode(grade.getGradeCode());
            vo.setGradeName(grade.getGradeName());
            vo.setMyTransMoney(statisticsVo == null ? BigDecimal.ZERO : statisticsVo.getMyTransMoney());//我的交易金额
            vo.setMyTerminalNum(statisticsVo == null ? BigDecimal.ZERO : statisticsVo.getMyTerminalNum());//我的终端数
            transUserInfoVo(vo);
        }
        return vo;
    }

    //手机号登录
    @Override
    public UserInfoVo loginByPhone(UserDto userDto) throws Exception {
        if (StringUtils.isEmpty(userDto.getUserPhone()) || StringUtils.isEmpty(userDto.getVerifyCode())) {
            throw new RuntimeException("手机号或密验证码不能为空");
        }
        /*String redisCode = redisCache.getVerifyCode(userDto.getUserPhone());
        if (!redisCode.equals(userDto.getVerifyCode())) { //校验验证码是否正确
            throw new RuntimeException("验证码错误，请重新输入");
        }*/
        TUserInfo user = userInfoMapper.selectUserByUserPhone(userDto.getUserPhone());
        if (StringUtils.isNull(user)) {
            throw new RuntimeException("暂无此账号,请注册");
        }
        if (YesOrNoEnums.NO.getCode().equals(user.getUserStatus())) {
            throw new RuntimeException("您已被禁用，无法完成登录");
        }

        redisCache.setUserToken(user.getToken(), user.getUserId());

        DataStatisticsDto dto = new DataStatisticsDto();
        dto.setUserId(user.getUserId());
        DataStatisticsVo statisticsVo = tStatisticInfoMapper.queryTStatisticSum(dto);
        TGradeInfo grade = tGradeInfoMapper.selectTGradeInfoById(user.getGradeId());

        UserInfoVo vo = new UserInfoVo();
        BeanUtils.copyProperties(user, vo);

        vo.setGradeCode(grade.getGradeCode());
        vo.setGradeName(grade.getGradeName());
        vo.setMyTransMoney(statisticsVo == null ? BigDecimal.ZERO : statisticsVo.getMyTransMoney());//我的交易金额
        vo.setMyTerminalNum(statisticsVo == null ? BigDecimal.ZERO : statisticsVo.getMyTerminalNum());//我的终端数
        transUserInfoVo(vo);
        return vo;
    }

    //账号密码登录
    @Override
    public UserInfoVo loginByAccount(UserDto userDto) throws Exception {
        if (StringUtils.isEmpty(userDto.getUserPhone()) || StringUtils.isEmpty(userDto.getPassword())) {
            throw new RuntimeException("手机号或密码不能为空");
        }
        TUserInfo user = userInfoMapper.selectUserByUserPhone(userDto.getUserPhone());
        if (StringUtils.isNull(user)) {
            throw new RuntimeException("暂无此账号,请注册");
        }
        if (!user.getPassword().equals(SaltUtils.salt(userDto.getPassword(), user.getSalt()))) {
            throw new RuntimeException("密码错误，请重新输入");
        }
        if (YesOrNoEnums.NO.getCode().equals(user.getUserStatus())) {
            throw new RuntimeException("您已被禁用，无法完成登录");
        }
        redisCache.setUserToken(user.getToken(), user.getUserId());

        DataStatisticsDto dto = new DataStatisticsDto();
        dto.setUserId(user.getUserId());
        DataStatisticsVo statisticsVo = tStatisticInfoMapper.queryTStatisticSum(dto);
        TGradeInfo grade = tGradeInfoMapper.selectTGradeInfoById(user.getGradeId());
        UserInfoVo vo = new UserInfoVo();
        BeanUtils.copyProperties(user, vo);
        vo.setGradeCode(grade.getGradeCode());
        vo.setGradeName(grade.getGradeName());
        vo.setMyTransMoney(statisticsVo == null ? BigDecimal.ZERO : statisticsVo.getMyTransMoney());//我的交易金额
        vo.setMyTerminalNum(statisticsVo == null ? BigDecimal.ZERO : statisticsVo.getMyTerminalNum());//我的终端数
        transUserInfoVo(vo);
        return vo;
    }

    //退出登录
    @Override
    public void loginOut() throws Exception {
        String token = commonUtils.getToken();
        redisCache.removeUserToken(token);
    }

    //生成邀请二维码
    public String createOrderQrCode(String orderId, String userUrl) throws Exception {
        JSONObject jo = new JSONObject();
        jo.put("orderId", orderId);
        jo.put("userUrl", userUrl);
        String url = userUrl + "?inviteCode=" + orderId;
        String qrCodePath = QrCodeUtils.createQRCodeDefultForDefultPath(orderId + ".jpg", url);
        qrCodePath = qrCodePath.replaceAll("\\\\", "/");
        return UrlUtils.getUrl() + Constants.RESOURCE_PREFIX + "/" + qrCodePath.substring(qrCodePath.indexOf(RuoYiConfig.getProfile()) + (RuoYiConfig.getProfile().length() + 1));
    }

    //翻译用户信息
    public UserInfoVo transUserInfoVo(UserInfoVo vo) {
        vo.setAuditStatusShow(AuditStatusEnum.getEnumsByCode(vo.getUserStatus()).getValue());
        vo.setUserStatusShow("");
        if (StringUtils.isNotEmpty(vo.getSuperiorUserId())) {
            TUserInfo supUser = userInfoMapper.selectTUserInfoByUserId(vo.getSuperiorUserId());
            vo.setSuperiorUserName(supUser.getUserName());
            vo.setMyServiceProviderName(supUser.getUserName());
            vo.setMyServiceProviderPhone(supUser.getUserPhone());
        }
        vo.setBalance(vo.getBalanceSum().subtract(vo.getBalanceUse()).subtract(vo.getBalanceWithdraw()));//用户当前可提现金额
        return vo;
    }
}
